#include <unistd.h>
#include "../Operacion.h"
#include "../../Excepciones/Excepcion_Operacion.h"
#include "Iterador_Archivos/IteradorArchivos.h"
#include "Extractor_Terminos/ExtratorTerminos.h"
//#include "../../MD5/Message_digest.h"
#include "Indexador/Indexador.h"
#ifndef INDICE_H
#define INDICE_H

typedef std::string tCodigoMD5;

class CodigoMD5_por_IdDoc{
private:
	tCodigoMD5 codigoMD5;
	tIdDoc idDoc;
public:
	CodigoMD5_por_IdDoc(){
		this->codigoMD5 = "";
		this->idDoc = 0;
	}
	CodigoMD5_por_IdDoc(tCodigoMD5 codigoMD5, tIdDoc idDoc){
		this->codigoMD5 = codigoMD5;
		this->idDoc = idDoc;
	}
	tCodigoMD5 getCodigoMD5() const{
		return this->codigoMD5;
	}
	tIdDoc gettIdDoc() const{
		return this->idDoc;
	}
	CodigoMD5_por_IdDoc& operator=(const CodigoMD5_por_IdDoc& unCodigoMD5_por_IdDoc){
		this->codigoMD5 = unCodigoMD5_por_IdDoc.getCodigoMD5();
		this->idDoc = unCodigoMD5_por_IdDoc.gettIdDoc();
		return (*this);
	}
	~CodigoMD5_por_IdDoc(){
	}
};

/*creacion temporal para simular el verdadero comportamiento de Message_Digest.
 * cuando este listo el verdadero Message_Digest se borra esta clase temporal y
 * se descomenta el include que esta mas arriba.
 * */
class Message_Digest{
private: const char* filename;
public: Message_Digest(const char* filename){ }
        virtual ~Message_Digest(){ }
        std::string obtener_resumen(){ return ("nada");}
};

/*
 *si el indice ya exite, o sea, que ya existe el archivo indice.dat(archivo que
 *contiene el indice persistido en disco) la ejecucion se torna distinta si el
 *contiene indice no existe. Ver implementacion de le metodo inicio.
 * */

//todo algunos metodos resien creados no fueron utilizados en el indexador por ahora(Ariel)
class Indice: public Operacion{
private:
	IteradorArchivos iterAchivos;
	ExtratorTerminos extratorTerminos;
	Indexador indexador;
	/*para que sea persistido de manera independiente a la Info de los terminos indexados
	 * */
	Lista<CodigoMD5_por_IdDoc>* codigosMD5_por_IdDoc;
	Lista<CodigoMD5_por_IdDoc>* codigosMD5_por_IdDoc_modificados;
	bool existencia_indice;

public:
	Indice(std::string& path);
	void inicio();
	bool getExistenciaIndice();
	/*
	 * se actualiza la lista 'codigosMD5_por_IdDoc'.
	 * todo  falta ver alguna posible verificacion a la aparicion de elementos de lista repetidos.
	 * */
	void agregarCodigoMD5_por_IdDoc(tCodigoMD5 codigoMD5, tIdDoc idDoc);

	void agregarCodigoMD5_por_IdDoc_modificados(tCodigoMD5 codigoMD5, tIdDoc idDoc);

	/*
	 * se utiliza la lista 'codigosMD5_por_IdDoc' luego de que sus elementos hallan sido
	 * cargados mediante de lo que se lee de disco. Esto se hace asi para evitar generar un
	 * codigo MD5 para indice.dat  y asi evitar la lectura de lectura de indice.dat. Tambien
	 * para saber a traves de 'codigosMD5_por_IdDoc_modificados' cuales fueron los documentos
	 * que cambiaron.
	 *
	 * */
	bool coleccionFueModificada();

	/*
	 * verifica que IdDoc pasado por parametro existe en la lista 'codigosMD5_por_IdDoc_modificados'
	 */
	bool existeIdDocEn_codigosMD5_por_IdDoc(tIdDoc idDoc);

	/*pre: primero se tiene que llamar al metodo 'existeIdDocEn_codigosMD5_por_IdDoc'
	 * return: codigo MD5 segun el idDoc pasado por parametro.
	 * */
	tCodigoMD5 getMD5segunIdDoc(tIdDoc idDoc);

private:
	/*
	 * */
	void calcularExistencia_delIndice();

	/*
	 * para transformar el filename_doc en su Id correspondiente.
	 * es un poco mas segura con respecto a la generacion de Id para un termino
	 * ya que todos los filename_doc de la coleccion son distintos, por ejemplo en el caso
	 * de que no pueden aparecer en la misma carpeta dos archivos con el mismo nombre.
	 * */
	tIdDoc generarIdDoc(std::string filename);
};
#endif
